var async = require('async');
var Wish = mongoose.model('wish');
var UserWish = mongoose.model('user_wish');

var WISH_STATUS = {1: '征集支持中', 2: '实现中', 3: '愿望失败', 4: '已实现'};
var WISH_TYPE = {1: "普通", 2: "精选"};

function validateWishStatus(userwish, callback) {
    var wishId = userwish._id;
    var status = userwish.status ? userwish.status : "";
    if (!userwish.status || !userwish.dateExpired || !userwish.wish || typeof userwish.wish != "object" || !userwish.wish.minSupport) {
        getWishFunc({_id: wishId}, function (err, result) {
            status = userwish.status;
            if (!err && result != null) {
                checkWishStatus(userwish);
            }
            if (status != userwish.status) {
                console.log("CHANGE IN WISH STATUS",wishId,status,"->>>",userwish.status);
                updateWishFunc({_id: wishId}, {'status': userwish.status}, callback);
            } else
                callback(err, userwish);
        })
    } else {
        checkWishStatus(userwish);
        if (status != userwish.status) {
            console.log("CHANGE IN WISH STATUS",wishId,status,"->>>",userwish.status);
            updateWishFunc({_id: wishId}, {'status': userwish.status}, callback);
        } else
            callback(null, userwish);
    }
}

function checkWishStatus(userwish) {
    var status = userwish.status;
    var expiryDate = new Date(userwish.dateExpired);
    var curDate = new Date();
    if (status != WISH_STATUS[1])
        return;
    if (userwish.wish && userwish.supporters.length > userwish.wish.minSupport) {
        userwish.status = WISH_STATUS[2];
    }
    else if (curDate > expiryDate) {
        userwish.status = WISH_STATUS[3];
    }
}

function addWishDetail(data, callback) {
    if (data.supporters)
        data.supportCount = data.supporters.length;
    if (data.status == WISH_STATUS[4] || data.status == WISH_STATUS[3])
        return;
    if (data.dateExpired) {
        var expiryDate = new Date(data.dateExpired);
        var curDate = new Date();
        if (expiryDate > curDate) {
            var timeLeft = (expiryDate - curDate) / (36e5 * 24);
            var daysLeft = Math.floor(timeLeft);
            var hoursLeft = (timeLeft - daysLeft) * 24;
            var minutesLeft = ((hoursLeft - Math.floor(hoursLeft)) * 60);
            var secondsLeft = ((minutesLeft - Math.floor(minutesLeft)) * 60);
            data.timeLeft = {
                days: daysLeft,
                hours: Math.floor(hoursLeft),
                minutes: Math.floor(minutesLeft),
                seconds: Math.floor(secondsLeft)
            }
        }
    }
    validateWishStatus(data, callback);
}

var wishPopulate = 'desc minSupport maxDays images';

function getWishFunc(query, callback) {
    UserWish.findOne(query).populate('wish', wishPopulate).exec(function (err, result) {
        if (!err && result != null) {
            addWishDetail(result, function () {
            });
        }
        callback(err, result);
        updateWishFunc({_id:result._id}, {"$inc":{"browseCount":1}}, function(){});
    })
}

function getWishListFunc(query, callback) {
    UserWish.find(query).sort({_id:-1}).populate('wish', wishPopulate).exec(function (err, result) {
        if (!err && result != null) {
            var lenn = result.length;
            for (var i = 0; i < lenn; ++i) {
                addWishDetail(result[i], function () {
                });
            }
        }
        callback(err, result);
    })
}

function updateWishFunc(query, updateObj, callback) {
    UserWish.update(query, updateObj).exec(callback);
}

exports.getWishService = function (wishId, callback) {
    Wish.findOne({'_id': wishId}).exec(callback);
};

exports.getWishDetailService = function (wishId, callback) {
    getWishFunc({'_id': wishId}, callback);
};

exports.getUserWishListService = function (wechatId, callback) {
    getWishListFunc({'createdBy': wechatId}, callback);
};

exports.getUserSupportedWishListService = function (wechatId, callback) {
    getWishListFunc({'supporters': wechatId}, callback);
};

exports.getJingxuanWishListService = function (callback) {
    getWishListFunc({type: WISH_TYPE[2]}, callback);
};

function randomWishGenerator(wishArray) {
    var sumOfWeights = 0;
    var cumulativeSumIdx = {};
    var lenn = wishArray.length;
    for(var i =0; i < lenn; ++i) {
        sumOfWeights += wishArray[i].weight;
        cumulativeSumIdx[i] = sumOfWeights;
    }
    var rndSum = Math.random() * sumOfWeights;
    var rndIdx = 0;
    for (var i in cumulativeSumIdx) {
        if (cumulativeSumIdx[i] > rndSum) {
            rndIdx = i;
            break;
        }
    }
    //console.log("RAND SUM", rndSum)
    //console.log("SUM WEIGHTS", sumOfWeights)
    //console.log("IDX", rndIdx, "DISCRETE SUM OF IDX", cumulativeSumIdx[rndIdx])
    //console.log(wishArray[rndIdx])
    return wishArray[rndIdx];
}

exports.getRandomWishService = function (wxuser, notWishes, callback) {
    // Get wish that user has not yet made / has not expired/ has not been fulfilled or deleted
    var condition = {createdBy: wxuser, isValid: true, status: WISH_STATUS[1], dateExpired: {$gte: new Date()}};
    UserWish.find(condition, 'wish', function (err, result) {
        if (!err && result != null) {
            var lenn = result.length;
            var exWishes = notWishes;
            for (var i = 0; i < lenn; ++i) {
                exWishes.push(result[i].wish);
            }
            var query = {'_id': {'$nin': exWishes}};
            Wish.find(query, function (err2, result) {
                if (!err2 && result.length > 0) {
                    callback(err2, randomWishGenerator(result));
                } else {
                    callback(err2, null);
                }
            });
            //Wish.count(query, function (err2, count) {
            //    if (err2 || count == 0) {
            //        callback(err2, null);
            //    } else {
            //        var rnd = Math.floor(Math.random() * count);
            //        Wish.findOne(query).skip(rnd).exec(function (err3, newwish) {
            //            callback(err3, newwish);
            //        })
            //    }
            //})
        } else {
            callback(err, result);
        }
    })
};

exports.makeWishService = function (wishId, user, callback) {

    Wish.findOne({_id: wishId}, 'maxDays', function (err, result) {
        if (!err && result != null) {
            var temp = new UserWish();
            var curdate = new Date();
            var expiryDate = new Date(curdate);
            expiryDate.setDate(expiryDate.getDate() + result.maxDays);

            temp.wish = wishId;
            temp.createdBy = user;

            //temp.status = 1;
            temp.status = WISH_STATUS[1];
            temp.type = WISH_TYPE[1];

            temp.dateCreated = curdate;
            temp.dateLastModified = temp.dateCreated;

            temp.dateExpired = expiryDate;
            temp.supporters = [];
            temp.isValid = true;

            temp.save(function (err2, result2) {
                callback(err2, result2);
            });
        } else {
            callback(err, null)
        }
    })
};

exports.updateWishService = function (wishId, input, callback) {
    updateWishFunc({_id: wishId}, input, callback);
};

exports.removeWishService = function (wishId, callback) {
    updateWishFunc({_id: wishId}, {isValid: false}, callback);
    //UserWish.remove({_id: wishId});
};

exports.solvedWishService = function (wishId, callback) {
    updateWishFunc({_id: wishId}, {status: WISH_STATUS[4]}, callback);
};

exports.addWishSupporterService = function (user, wishId, callback) {
    updateWishFunc({_id: wishId}, {
        $addToSet: {'supporters': user},  // don't use push, since push can result in duplicates
        dateLastModified: new Date()
    }, callback);
};

exports.removeWishSupporterService = function (user, wishId, callback) {
    updateWishFunc({_id: wishId}, {
        $pull: {'supporters': user},
        dateLastModified: new Date()
    }, callback);
};

exports.shareWishService = function (user, wishId, callback) {
    //
};
